home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / ada / adaed-1.11 / adaed-1 / Adaed-1.11.0a / predef2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-07  |  12.1 KB  |  467 lines

  1. /*
  2.  * Copyright (C) 1985-1992  New York University
  3.  * 
  4.  * This file is part of the Ada/Ed-C system.  See the Ada/Ed README file for
  5.  * warranty (none) and distribution info and also the GNU General Public
  6.  * License for more details.
  7.  
  8.  */
  9. /*    +---------------------------------------------------+
  10.       |                                                   |
  11.       |          I N T E R P     P R E D E F S            |
  12.       |            Part 2: CALENDAR Procedure             |
  13.       |                  (C Version)                      |
  14.       |                                                   |
  15.       |   Adapted From Low Level SETL version written by  |
  16.       |                                                   |
  17.       |                  Monte Zweben                     |
  18.       |               Philippe Kruchten                   |
  19.       |               Jean-Pierre Rosen                   |
  20.       |                                                   |
  21.       |    Original High Level SETL version written by    |
  22.       |                                                   |
  23.       |                   Clint Goss                      |
  24.       |               Tracey M. Siesser                   |
  25.       |               Bernard D. Banner                   |
  26.       |               Stephen C. Bryant                   |
  27.       |                  Gerry Fisher                     |
  28.       |                                                   |
  29.       |              C version written by                 |
  30.       |                                                   |
  31.       |               Robert B. K. Dewar                  |
  32.       |                                                   |
  33.       +---------------------------------------------------+
  34. */
  35.  
  36. /* This module contains the implementation of the CALENDAR package */
  37.  
  38. #include "ipredef.h"
  39. #include "time.h"
  40. #include "intbprots.h"
  41. #include "intcprots.h"
  42. #include "predefprots.h"
  43.  
  44. /* Structure corresponding to Ada record TIME */
  45.  
  46. struct time_record {
  47.     int     year_val;
  48.     int     month_val;
  49.     int     day_val;
  50.     long    secs_val;
  51. };
  52.  
  53. static long days_in(int, int, int);
  54. static void ymd_of(long days, int *, int *, int *);
  55. static void get_time(struct time_record *);
  56.  
  57. /*  Macros for treating pointer as pointer to time_record, and length in
  58.  *  words of time record(used when creating an object of this type.
  59.  */
  60.  
  61. #define TIME_RECORD(ptr)    ((struct time_record *)(ptr))
  62. #define WORDS_TIME_RECORD   (sizeof(struct time_record) / sizeof (int))
  63.  
  64. /*  Constants for CALENDAR */
  65.  
  66. #define ONE_DAY   86400000L       /* 24 * 60 * 60 * 1000 (milliseconds) */
  67.  
  68. static int days_before_month[] = {
  69.     0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
  70. };
  71.  
  72. static int days_in_month[] = {
  73.     0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  74. };
  75.  
  76.  
  77. /* CALENDAR */
  78.  
  79. /* Control passes to the CALENDAR procedure from PREDEF when it encounters an
  80.  * operation code value corresponding to a predefined calendar operation.
  81. */
  82.  
  83. void calendar()                                                  /*;calendar*/
  84. {
  85.     switch(operation) {
  86.  
  87.         /* function CLOCK return TIME; */
  88.  
  89.     case P_CLOCK:
  90.         {
  91.             int    bse, off;
  92.             int    *ptr;
  93.  
  94.             create(WORDS_TIME_RECORD, &bse, &off, &ptr);
  95.             get_time((struct time_record  *) ptr);
  96.             TOSM(1) = bse;
  97.             TOS = off;
  98.             break;
  99.         }
  100.  
  101.  
  102.         /* function YEAR(DATE : in TIME) return YEAR_NUMBER; */
  103.  
  104.     case P_YEAR:
  105.         TOSM(2) = TIME_RECORD(get_argument_ptr(0)) -> year_val;
  106.         break;
  107.  
  108.         /* function MONTH(DATE : in TIME) return MONTH_NUMBER; */
  109.  
  110.     case P_MONTH:
  111.         TOSM(2) = TIME_RECORD(get_argument_ptr(0)) -> month_val;
  112.         break;
  113.  
  114.         /* function DAY(DATE : in TIME) return DAY_NUMBER; */
  115.  
  116.     case P_DAY:
  117.         TOSM(2) = TIME_RECORD(get_argument_ptr(0)) -> day_val;
  118.         break;
  119.  
  120.         /* function SECONDS(DATE : in TIME) return DURATION; */
  121.  
  122.     case P_SECONDS:
  123.         {
  124.             int  bse,off;
  125.             long secs,tmp;
  126.  
  127.             /*TOSM(2) = TIME_RECORD(get_argument_ptr(0)) -> secs_val;*/
  128.             /* direct code needed since TOSML macro wrong */
  129.             /* pop arguments, store long and restore args */
  130.             secs = TIME_RECORD(get_argument_ptr(0)) -> secs_val;
  131.             POP_ADDR(bse,off);
  132.             POPL(tmp); /* pop current value */
  133.             PUSHL(secs); /* push correct value */
  134.             PUSH_ADDR(bse,off); /* restore arg on stack */
  135.         }
  136.         break;
  137.  
  138.         /* procedure SPLIT(DATE      : in  TIME;          */
  139.         /*                 YEAR      : out YEAR_NUMBER;   */
  140.         /*                 MONTH     : out MONTH_NUMBER;  */
  141.         /*                 DAY       : out DAY_NUMBER;    */
  142.         /*                 SECONDS   : out DURATION);     */
  143.  
  144.     case P_SPLIT:
  145.         {
  146.             struct time_record *time_ptr;
  147.             long *p;
  148.  
  149.             time_ptr = TIME_RECORD(get_argument_ptr(0));
  150.  
  151.             *get_argument_ptr(2)  = time_ptr -> year_val;
  152.             *get_argument_ptr(6)  = time_ptr -> month_val;
  153.             *get_argument_ptr(10) = time_ptr -> day_val;
  154.             p = (long *) get_argument_ptr(14) ;
  155.             *p = time_ptr -> secs_val;
  156.             break;
  157.         }
  158.  
  159.         /* function TIME_OF(YEAR     : YEAR_NUMBER;                   */
  160.         /*                  MONTH    : MONTH_NUMBER;                  */
  161.         /*                  DAY      : DAY_NUMBER;                    */
  162.         /*                  SECONDS  : DURATION := 0.0) return TIME;  */
  163.  
  164.     case P_TIME_OF:
  165.         {
  166.             int    year, month, day;
  167.             long   secs;
  168.             long   days;
  169.             int    bse, off;
  170.             struct time_record *time_ptr;
  171.  
  172.             year  = get_argument_value(0);
  173.             month = get_argument_value(2);
  174.             day   = get_argument_value(4);
  175.             secs  = get_long_argument_value(6);
  176.  
  177.             if ((year % 4) == 0 && month == 2) {
  178.                 if (day > 29) { /* check leap year */
  179.                     raise(TIME_ERROR, "Day too large");
  180.                     return;
  181.                 }
  182.             }
  183.             else if (day > days_in_month[month]) {
  184.                 raise(TIME_ERROR, "Day too large");
  185.                 return;
  186.             }
  187.             if (secs >= ONE_DAY) {
  188.                 secs -= ONE_DAY;
  189.                 days = days_in(year, month, day + 1);
  190.                 ymd_of(days, &year, &month, &day);
  191.                 if (year < 1901 || year > 2099) {
  192.                     raise(TIME_ERROR, "Year out of range");
  193.                     return;
  194.                 }
  195.             }
  196.             create(WORDS_TIME_RECORD, &bse, &off,(int **)(&time_ptr));
  197.             time_ptr -> year_val  = year;
  198.             time_ptr -> month_val = month;
  199.             time_ptr -> day_val   = day;
  200.             time_ptr -> secs_val  = secs;
  201.             TOSM(9) = bse;
  202.             TOSM(8) = off;
  203.             break;
  204.         }
  205.  
  206.         /* function "+"(LEFT : TIME;     RIGHT : DURATION)  return TIME; */
  207.         /* function "+"(LEFT : DURATION; RIGHT : TIME)      return TIME; */
  208.         /* function "-"(LEFT : TIME;     RIGHT : DURATION)  return TIME; */
  209.  
  210.     case P_ADD_TIME_DUR:
  211.     case P_ADD_DUR_TIME:
  212.     case P_SUB_TIME_DUR:
  213.         {
  214.             struct time_record *time_ptr;
  215.             long   dur;
  216.             int    year, month, day;
  217.             long   secs,days;
  218.             int    add_day;
  219.             int    bse, off;
  220.  
  221.             if (operation == P_ADD_TIME_DUR) {
  222.                 time_ptr = TIME_RECORD(get_argument_ptr(0));
  223.                 dur = get_long_argument_value(2);
  224.             }
  225.             else if (operation == P_ADD_DUR_TIME) {
  226.                 dur = get_long_argument_value(0);
  227.                 time_ptr = TIME_RECORD(get_argument_ptr(2));
  228.             }
  229.             else { /* operation == P_SUB_TIME_DUR */
  230.                 time_ptr = TIME_RECORD(get_argument_ptr(0));
  231.                 dur = - get_long_argument_value(2);
  232.             }
  233.  
  234.             year  = time_ptr -> year_val;
  235.             month = time_ptr -> month_val;
  236.             day   = time_ptr -> day_val;
  237.             secs  = time_ptr -> secs_val;
  238.  
  239.             secs += dur;
  240.             add_day = (int)(secs / ONE_DAY);
  241.             secs -= add_day * ONE_DAY;
  242.             if (secs < 0) {
  243.                 secs += ONE_DAY;
  244.                 add_day--;
  245.             }
  246.  
  247.             day += add_day;
  248.  
  249.             days = days_in(year, month, day);
  250.             if (days <= 0) {
  251.                 raise(TIME_ERROR, "Year out of range");
  252.                 return;
  253.             }
  254.             ymd_of(days, &year, &month, &day);
  255.             if (year < 1901 || year > 2099) {
  256.                 raise(TIME_ERROR, "Year out of range");
  257.                 return;
  258.             }
  259.             create(WORDS_TIME_RECORD, &bse, &off,(int **)(&time_ptr));
  260.             time_ptr -> year_val  = year;
  261.             time_ptr -> month_val = month;
  262.             time_ptr -> day_val   = day;
  263.             time_ptr -> secs_val  = secs;
  264.  
  265.             TOSM(5) = bse;
  266.             TOSM(4) = off;
  267.             break;
  268.         }
  269.  
  270.         /* function "-"(LEFT : TIME; RIGHT : TIME) return DURATION; */
  271.  
  272.     case P_SUB_TIME_TIME:
  273.         {
  274.             int    *dur_tt_ptr;
  275.             int    *left_ptr;
  276.             int    *right_ptr;
  277.             int    y1, m1, d1;
  278.             int    y2, m2, d2;
  279.             long   s1, s2, secs, days;
  280.             long   dur;
  281.             struct time_record *time_ptr;
  282.             int    bse, off, bse1, off1;
  283.  
  284.             POP_PTR(dur_tt_ptr);               /* type must be popped */
  285.  
  286.             left_ptr  = get_argument_ptr(0);
  287.             right_ptr = get_argument_ptr(2);
  288.  
  289.             time_ptr = TIME_RECORD(left_ptr);
  290.             y1 = time_ptr -> year_val;
  291.             m1 = time_ptr -> month_val;
  292.             d1 = time_ptr -> day_val;
  293.             s1 = time_ptr -> secs_val;
  294.  
  295.             time_ptr = TIME_RECORD(right_ptr);
  296.             y2 = time_ptr -> year_val;
  297.             m2 = time_ptr -> month_val;
  298.             d2 = time_ptr -> day_val;
  299.             s2 = time_ptr -> secs_val;
  300.  
  301.             days = days_in(y1, m1, d1) - days_in(y2, m2, d2);
  302.             secs = s1 - s2;
  303.             dur = ONE_DAY * days + secs;
  304.  
  305.             if (fix_out_of_bounds(dur, (int *)FX_RANGE(dur_tt_ptr)))
  306.                 raise(TIME_ERROR, "Out of range");
  307.             else {
  308.                 /* direct code needed since TOSML macro wrong */
  309.                 /* pop arguments, store long and restore args */
  310.                 POP_ADDR(bse,off);
  311.                 POP_ADDR(bse1,off1);
  312.                 POPL(secs); /* pop current value */
  313.                 PUSHL(dur); /* push correct value */
  314.                 PUSH_ADDR(bse1,off1); /* restore args on stack */
  315.                 PUSH_ADDR(bse,off);
  316.             }
  317.             break;
  318.         }
  319.  
  320.         /* function "<"  (LEFT, RIGHT : TIME) return BOOLEAN; */
  321.         /* function "<=" (LEFT, RIGHT : TIME) return BOOLEAN; */
  322.         /* function ">"  (LEFT, RIGHT : TIME) return BOOLEAN; */
  323.         /* function ">=" (LEFT, RIGHT : TIME) return BOOLEAN; */
  324.  
  325.     case P_LT_TIME:
  326.     case P_LE_TIME:
  327.     case P_GT_TIME:
  328.     case P_GE_TIME:
  329.         {
  330.             int    *left_ptr;
  331.             int    *right_ptr;
  332.             int    y1, m1, d1;
  333.             int    y2, m2, d2;
  334.             long   s1, s2;
  335.             long   dur1, dur2;
  336.             long   days1, days2;
  337.             struct time_record *time_ptr;
  338.             int    result;
  339.  
  340.             left_ptr  = get_argument_ptr(0);
  341.             right_ptr = get_argument_ptr(2);
  342.  
  343.             time_ptr = TIME_RECORD(left_ptr);
  344.             y1 = time_ptr -> year_val;
  345.             m1 = time_ptr -> month_val;
  346.             d1 = time_ptr -> day_val;
  347.             s1 = time_ptr -> secs_val;
  348.  
  349.             time_ptr = TIME_RECORD(right_ptr);
  350.             y2 = time_ptr -> year_val;
  351.             m2 = time_ptr -> month_val;
  352.             d2 = time_ptr -> day_val;
  353.             s2 = time_ptr -> secs_val;
  354.  
  355.             days1 = days_in(y1, m1, d1);
  356.             days2 = days_in(y2, m2, d2);
  357.             if (days1 == days2) {
  358.                 dur1 = s1;
  359.                 dur2 = s2;
  360.             }
  361.             else {
  362.                 dur1 = days1;
  363.                 dur2 = days2;
  364.             }
  365.  
  366.             if (operation == P_LT_TIME)
  367.                 result = dur1 < dur2;
  368.             else if (operation == P_LE_TIME)
  369.                 result = dur1 <= dur2;
  370.             else if (operation == P_GT_TIME)
  371.                 result = dur1 > dur2;
  372.             else /*(operation == P_GE_TIME) */
  373.                 result = dur1 >= dur2;
  374.  
  375.             TOSM(4) = result;
  376.             break;
  377.         }
  378.     }
  379. }
  380.  
  381.  
  382. /* DAYS_IN */
  383.  
  384. /* Given integer arguments(such as 1981, 2, 28), days_in computes the
  385.  * number of days since January 1st, 1901. Since Ada does not allow dates
  386.  * before 1901 or after 2099, we do not need to consider leap centuries.
  387. */
  388.  
  389. static long days_in(int y, int m, int d)                        /*;days_in*/
  390. {
  391.     return
  392.         (y - 1901) * 365L +(y - 1901) / 4 +
  393.         days_before_month[m] +((y % 4) ? 0 :(m > 2)) + d;
  394. }
  395.  
  396.  
  397. /* YMD_OF */
  398.  
  399. /* Given an integer which is the number of days since January 1st, 1901
  400.  * this function returns the corresponding date in year/month/day form
  401. */
  402.  
  403. static void ymd_of(long days, int *y, int *m, int *d)              /*;ymf_of*/
  404. {
  405.     *y = 1901 +(int)((days * 4 - 1) / 1461);/*(4 * 365 + 1) */
  406.     *d = (int)(days -((*y - 1901) * 365 +(*y - 1901) / 4));
  407.     if (!(*y % 4)) {
  408.         if (*d == 60) {
  409.             *d = 29;
  410.             *m = 2;
  411.             return;
  412.         }
  413.         else if (*d > 60)
  414.             *d -= 1;
  415.     }
  416.     *m = 1;
  417.     while(*d > days_in_month[*m])
  418.         *d -= days_in_month[(*m)++];
  419. }
  420.  
  421. /* GET_TIME */
  422.  
  423. /* Get date and time. The format of the result is:
  424.  *
  425.  *      struct time_record = {
  426.  *         int year_val;
  427.  *         int month_val;
  428.  *         int day_val;
  429.  *         long secs_val;
  430.  *      };
  431. */
  432.  
  433. static void get_time(struct time_record *time_ptr)                /*;get_time*/
  434. {
  435.     long    itime();
  436. #ifndef IBM_PC
  437.     long clock;
  438. #else
  439.     /* IBM_PC (Metaware) */
  440.     time_t clock;
  441. #endif
  442.     struct tm *t;
  443. #ifndef IBM_PC
  444.     clock = time(0);
  445. #else
  446.     time(&clock);
  447. #endif
  448.     t = localtime(&clock);
  449. #ifdef IBM_PC
  450.     /* needed until Metaware fixes bug in tm_year field (ds 6-19-86) */
  451.     time_ptr -> year_val = t -> tm_year;
  452. #else
  453.     time_ptr -> year_val = 1900 + t -> tm_year;
  454. #endif
  455.     time_ptr -> month_val = t -> tm_mon + 1;
  456.     time_ptr -> day_val = t -> tm_mday;
  457.     time_ptr -> secs_val = itime() % ONE_DAY;
  458.     if (instruction_trace) {
  459.         printf("get_time year %d month %d day %d secs %ld secs_chk %ld\n",
  460.           time_ptr -> year_val, time_ptr -> month_val,
  461.           time_ptr -> day_val, time_ptr -> secs_val, 
  462.           ((long)t->tm_hour*3600 + (long) t->tm_min * 60 
  463.           + (long) t->tm_sec)*1000L);
  464.     }
  465.     return;
  466. }
  467.